package com.objecteffects.template.web.action;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.google.inject.Inject;

import com.objecteffects.template.model.TumblrBlogEntity;
import com.objecteffects.template.model.UserEntity;
import com.objecteffects.template.oauth.Tumblr;
import com.objecteffects.template.service.UserEntityService;
import com.objecteffects.template.util.logger.InjectLogger;
import com.objecteffects.template.web.utils.LoginRequired;

import org.scribe.builder.ServiceBuilder;
import org.scribe.builder.api.TumblrApi;
import org.scribe.model.Token;
import org.scribe.oauth.OAuthService;

import org.slf4j.Logger;

import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.validation.Validate;

/**
 * @author Rusty Wright
 */
@LoginRequired
public class TumblrMethodsTestActionBean extends BaseActionBean {
    @InjectLogger
    private Logger log;

    @Validate(required = true, on = {
        "proceed"
    })
    private String tumblrUrl; // = "rustycwright.tumblr.com";

    private final List<String> methods = new ArrayList<>();
    private final List<String> tumblrUrls = new ArrayList<>();

    private final UserEntityService userEntityService;

    private String method;

    @Inject
    TumblrMethodsTestActionBean(final UserEntityService _userEntityService) {
        this.userEntityService = _userEntityService;
    }

    @DefaultHandler
    public Resolution startHandler() throws Exception {
        final UserEntity userEntity =
            this.userEntityService.findById(this.getContext().getUserId());

        this.log.debug("userEntity: {}", userEntity);

        for (final TumblrBlogEntity each : userEntity.getTumblrBlogEntities()) {
            this.tumblrUrls.addAll(each.getUrls());
        }

        Collections.sort(this.tumblrUrls);

        for (final TumblrMethod tumblrMethod : TumblrMethod.values()) {
            if (tumblrMethod.toActionBean() != null) {
                this.methods.add(tumblrMethod.toString());
            }
        }

        Collections.sort(this.methods);

        return new ForwardResolution(TemplateView.TUMBLR_METHODS_TEST);
    }

    public Resolution proceed() {
        this.log.debug("proceed");

        this.log
            .debug("method: {}, tumblrUrl: {}", this.method, this.tumblrUrl);

        if (this.hasAccessToken()) {
            return new RedirectResolution(TumblrResponseUrlActionBean.class);
        }

        this.getContext().setTumblrUrl(this.tumblrUrl);

        final String authUrl = this.authUrl();

        /*
         * Step 3
         * 
         * This goes to tumblr for authentication, that redirects to
         * TumblrCallbackActionBean, that redirects to
         * TumblrResponseAllActionBean, and that redirects to the
         * action bean that calls the tumblr METHOD.
         */
        return new RedirectResolution(authUrl, false);
    }

    /**
     * @return
     */
    private String authUrl() {
        final String callbackUrl =
            "http://" + this.getContext().getRequest().getServerName() + ":" +
                this.getContext().getRequest().getServerPort() +
                Tumblr.CALLBACK_PATH;

        this.log.debug("callbackUrl: {}", callbackUrl);

        // Step 1
        final OAuthService service =
            new ServiceBuilder().provider(TumblrApi.class)
            .apiKey(Tumblr.CONSUMER_KEY).apiSecret(Tumblr.CONSUMER_SECRET)
            .callback(callbackUrl).build();

        /*
         * temporary credentials; scribe Token includes token and
         * secret
         */
        final Token requestToken = service.getRequestToken();

        this.log.debug("requestToken: {}", requestToken.getToken());

        this.getContext().setRequestToken(requestToken);

        // Step 3
        final String authUrl = service.getAuthorizationUrl(requestToken);

        this.log.debug(String.format("authUrl: %s", authUrl));

        return authUrl;
    }

    private boolean hasAccessToken() {
        final Token accessTokenFUE =
            this.accessTokenFromUserEntity(this.tumblrUrl);

        if (accessTokenFUE != null) {
            this.log.debug("found access token in userEntity");

            return true;
        }

        return false;
    }

    private Token accessTokenFromUserEntity(final String url) {
        final UserEntity userEntity =
            this.userEntityService.findById(this.getContext().getUserId());

        // this.userEntityService.findByUsername(this.getContext().getUser()
        // .getUsername());

        // final Map<String, Token> map = userEntity.getTumblrBlogs();

        // if (map.containsKey(url)) {
        // return map.get(url);
        // }

        for (final TumblrBlogEntity each : userEntity.getTumblrBlogEntities()) {
            if (each.getUrls().contains(url)) {
                return each.getAccessToken();
            }
        }

        return null;
    }

    public List<String> getTumblrUrls() {
        return this.tumblrUrls;
    }

    public List<String> getMethods() {
        return this.methods;
    }

    public String getTumblrUrl() {
        return this.tumblrUrl;
    }

    public void setTumblrUrl(final String _tumblrUrl) {
        this.tumblrUrl = _tumblrUrl;
    }

    public String getMethod() {
        return this.method;
    }

    public void setMethod(final String _method) {
        this.method = _method;
    }
}
